#!/usr/bin/env python

import argparse
import contextlib
import errno
import os
import subprocess
import sys

import lib.filesystem as filesystem
import lib.git as git

from lib.config import PLATFORM_KEY, SOURCE_ROOT, TOOLS_DIR

SHARED_LIBRARY_FILENAME = 'libchromiumcontent.tar.bz2'
STATIC_LIBRARY_FILENAME = 'libchromiumcontent-static.tar.bz2'


class ProgramError(Exception):
  pass


def main():
  try:
    args = parse_args()
    if (args.libcc_source_path != None and
        args.libcc_shared_library_path != None and
        args.libcc_static_library_path != None):
      if (not os.path.isdir(args.libcc_source_path)):
        print "Error: Directory does not exist:", args.libcc_source_path
        sys.exit(0)
      generate_filenames_gypi(os.path.join(args.path, 'filenames.gypi'),
                              args.libcc_source_path,
                              args.libcc_shared_library_path,
                              args.libcc_static_library_path)
    elif (args.libcc_source_path != None or
          args.libcc_shared_library_path != None or
          args.libcc_static_library_path != None):
      print "Error: All options of libchromiumcontent are required OR let libchromiumcontent choose it"
      sys.exit(0)
    else:
      if args.commit == 'HEAD':
        commit = git.get_head_commit(SOURCE_ROOT)
      else:
        commit = args.commit
      if os.environ.has_key('MAS_BUILD'):
        platform = 'mas'
      else:
        platform = PLATFORM_KEY
      base_url = '{0}/{1}/{2}'.format(args.url, platform, args.target_arch)
      download_if_needed(args.path, base_url, commit, SHARED_LIBRARY_FILENAME,
                         args.force, args.verbose)
      if (args.static and
          not os.path.exists(os.path.join(args.path, 'static_library'))):
        download(args.path, base_url, commit, STATIC_LIBRARY_FILENAME,
                 args.verbose)
      generate_filenames_gypi(os.path.join(args.path, 'filenames.gypi'),
                              os.path.join(args.path, 'src'),
                              os.path.join(args.path, 'shared_library'),
                              os.path.join(args.path, 'static_library'))
    with open(os.path.join(args.path, '.target_arch'), 'w') as f:
      f.write(args.target_arch)
  except ProgramError as e:
    return e.message


def parse_args():
  parser = argparse.ArgumentParser(description='Download and extract '
                                   'libchromiumcontent')
  parser.add_argument('-f', '--force', action='store_true',
                      help='Overwrite destination if it already exists.')
  parser.add_argument('-c', '--commit', nargs='?', default='HEAD',
                      help='The commit of libchromiumcontent to download.')
  parser.add_argument('-s', '--static', action='store_true',
                      help='Download static_library build')
  parser.add_argument('--target_arch', required=True,
                      help='The arch of libchromiumcontent to download.')
  parser.add_argument('url', help='The base URL from which to download '
                      '(i.e., the URL you passed to script/upload)')
  parser.add_argument('path', help='The path to extract to')
  parser.add_argument('--libcc_source_path', required=False,
                        help='The source path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let libchromiumcontent choose it')
  parser.add_argument('--libcc_shared_library_path', required=False,
                        help='The shared library path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let libchromiumcontent choose it')
  parser.add_argument('--libcc_static_library_path', required=False,
                        help='The static library path of libchromiumcontent. NOTE: All options of libchromiumcontent are required OR let libchromiumcontent choose it')
  parser.add_argument('-v', '--verbose',
                      action='store_true',
                      help='Prints verbose download stats')
  return parser.parse_args()


def download_if_needed(destination, base_url, commit, filename, force, verbose):
  version_file = os.path.join(destination, '.version')
  existing_version = ''
  try:
    with open(version_file, 'r') as f:
      existing_version = f.readline().strip()
  except IOError as e:
    if e.errno != errno.ENOENT:
      raise
  if existing_version == commit:
    return

  if force:
    filesystem.rm_rf(destination)
  elif os.path.exists(destination):
    raise ProgramError('Error: {0} already exists. Pass --force if you '
                       'want to overwrite it.'.format(destination))

  download(destination, base_url, commit, filename, verbose)

  with open(version_file, 'w') as f:
    f.write('{0}\n'.format(commit))


def download(destination, base_url, commit, filename, verbose):
  sys.stderr.write('Downloading {0}...\n'.format(filename))
  sys.stderr.flush()
  url = '{0}/{1}/{2}'.format(base_url, commit, filename)
  filesystem.download_and_extract(destination, url, verbose)


def generate_filenames_gypi(target_file, libcc_source_path,
                            libcc_shared_library_path,
                            libcc_static_library_path):
  generate = os.path.join(TOOLS_DIR, 'generate_filenames_gypi.py')
  subprocess.check_call([sys.executable, generate] + [target_file,
                         libcc_source_path, libcc_shared_library_path,
                         libcc_static_library_path])


if __name__ == '__main__':
  sys.exit(main())
